package task2;

import java.util.Collection;
import java.util.LinkedList;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class CyclicBufferWithLock<E> extends LinkedList<E> {

	/**
	 * 
	 */
	private static final long serialVersionUID = 4134599162057405079L;

	private int MAX_SIZE;
	private static final Lock bufferLock = new ReentrantLock();
	private static final Condition bufferNotEmpty = bufferLock.newCondition();
	private static final Condition bufferNotFull = bufferLock.newCondition();

	public CyclicBufferWithLock() {
		this(10);
	}

	public CyclicBufferWithLock(int max_size) {
		super();
		MAX_SIZE = max_size;		
	}

	public CyclicBufferWithLock(Collection<? extends E> c) {
		super(c);
		MAX_SIZE = c.size();
	}

	public boolean isFull() {
		return (size() == MAX_SIZE);
	}

	public void put(final E e) throws InterruptedException {
		bufferLock.lock();
		
		try {
			while (isFull()) {
				bufferNotFull.await();
			}

			addLast(e);
			bufferNotEmpty.signal();
		} finally {
			bufferLock.unlock();
	    }
		
	}

	public E retrieve() throws InterruptedException {
		bufferLock.lock();
		
		try {
			while (isEmpty()) {
				bufferNotEmpty.await();
			}

			bufferNotFull.signal();
			return removeLast();
		} finally {
			bufferLock.unlock();
		}
	}

	public String retrieveString() throws InterruptedException {
		bufferLock.lock();
		
		try {
			while (isEmpty()) {
				bufferNotEmpty.await();
			}

			bufferNotFull.signal();
			return (String) removeLast();
		} finally {
			bufferLock.unlock();
		}
	}
}